Micron Document




First-class function
part 7/20 · 35.2 KB total
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
In languages supporting anonymous functions, we can pass such a function as an argument to a higher-order function:

main = map (\x -> 3 * x + 1) [1, 2, 3, 4, 5]

In a language which does not support anonymous functions, we have to bind it to a name instead:

int f(int x) {
return 3 * x + 1;
}
int main() {
int list[] = {1, 2, 3, 4, 5};
map(f, list, 5);
}

Non-local variables and closures

Once we have anonymous or nested functions, it becomes natural for them to refer to variables outside of their body (called non-local variables):

main = let a = 3
b = 1
in map (\x -> a * x + b) [1, 2, 3, 4, 5]

If functions are represented with bare function pointers, we can not know anymore how the value that is outside of the function's body should be passed to it, and because of that a closure needs to be built manually. Therefore we can not speak of "first-class" functions here.

typedef struct {
int (*f)(int, int, int);
int a;
int b;
} closure_t;
void map(closure_t *closure, int x[], size_t n) {
for (int i = 0; i < n; ++i)
x[i] = (closure->f)(closure->a, closure->b, x[i]);
}
int f(int a, int b, int x) {
return a * x + b;
}
void main() {
int l[] = {1, 2, 3, 4, 5};
int a = 3;
int b = 1;
closure_t closure = {f, a, b};
map(&closure, l, 5);
}

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────